home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Magazin/MacEasy 12
/
Mac Magazin and MacEasy Magazine CD - Issue 12.iso
/
Sharewarebibliothek
/
Anwendungen
/
Wissenschaft & Technik
/
ResAnomaly 1.1
/
ResAnomaly Source
/
FrDropApp.cp
next >
Wrap
Text File
|
1995-07-03
|
9KB
|
378 lines
// * This is ResAnomaly. Based on FrDropApp
// * ©1995 Chris K. Thomas. ©1994 Metrowerks Inc. All Rights Reserved.
/*
ckt July the Second 1995
Grab text resources up front to support the current architecture of
ResAnomaly. Eventually, I think we're going to go to three stages:
…resource file is open
Stage One: Data retrieval. Gather all the named resources
in the file into a list.
…resource file is closed
Stage Two: Analysis. Check to be sure
there aren't duplicate names & other stuff
Stage Three: Emitter. Write the data in the proper format
to the output stream.
Currently, we only effectively have a mixed version of stages 1 & 3,
and the resource file is open throughout, which makes it difficult
to get to our own resources without abusing the Resource Mangler.
*/
#define DEBUG_ME Yes, Please
#if (defined DEBUG_ME) && (defined __powerc)
#pragma traceback on
#endif
// ————• Us
#include "FrDropApp.h"
#include "ResAnomaly Settings.h"
// ————• PP
#include <UException.h>
#include <LModelDirector.h>
#include <LFileStream.h>
#include <UAppleEventsMgr.h>
#include <LHandleStream.h>
#include <UMemoryMgr.h>
// ————• my less annoying (to the programmer) standard file replacement
#include "StFile.h"
const ResIDT ALRT_NoFiles = 200;
static void InsertTextIntoStream(Handle inOurResource, LStream &inStream);
static void InsertTextIntoStream(short inID, LStream &inStream);
static void AddDotExtension(Str255 ioString, const Str255 inDot);
static void MapToValidC(Str255 ioString);
// ===========================================================================
// • Main Program
// ===========================================================================
void main(void)
{
try
{
FrDropApp gApp;
gApp.Run();
}
catch(...)
{
}
}
// ===========================================================================
// • FrDropApp Class
// ===========================================================================
FrDropApp::FrDropApp()
{
MaxApplZone();
InitGraf((Ptr) &qd.thePort); // Toolbox Managers
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(nil);
new LModelDirector(this); // AppleEvent Handlers
mRunning = true;
// * preload our text, because we can't access
// * our res file during processing
mTextBeginLine = Get1Resource('TEXT', 128);
mTextIDequals = Get1Resource('TEXT', 130);
mTextIDend = Get1Resource('TEXT', 131);
mOutputHeaderStart = Get1Resource('TEXT', 256);
mOutputHeaderStop = Get1Resource('TEXT', 257);
ThrowIfNULL_(mTextBeginLine);
ThrowIfNULL_(mTextIDequals);
ThrowIfNULL_(mTextIDend);
ThrowIfNULL_(mOutputHeaderStart);
ThrowIfNULL_(mOutputHeaderStop);
}
void
FrDropApp::Run()
{
// This program has no user interface. We only care
// about AppleEvents.
while (mRunning) {
EventRecord macEvent;
if (WaitNextEvent(everyEvent, &macEvent, 2, nil)) {
if (macEvent.what == kHighLevelEvent) {
AEProcessAppleEvent(&macEvent);
}
}
}
}
void
FrDropApp::HandleAppleEvent(
const AppleEvent &inAppleEvent,
AppleEvent &outAEReply,
AEDesc &outResult,
long inAENumber)
{
switch (inAENumber) {
case ae_OpenApp:
StartUp();
break;
case ae_OpenDoc:
DoAEOpenDoc(inAppleEvent, outAEReply, inAENumber);
break;
case ae_Quit:
DoQuit();
break;
default:
LModelObject::HandleAppleEvent(inAppleEvent, outAEReply, outResult, inAENumber);
break;
}
}
void
FrDropApp::StartUp()
{
// User double-clicked on the Program's icon
// This program only works when files are dragged on the
// program's icon in the Finder. So we just display an
// Alert (which could have instructions for using the program)
// and then quit.
::Alert(ALRT_NoFiles, nil);
DoQuit();
}
void
FrDropApp::DoAEOpenDoc(
const AppleEvent &inAppleEvent,
AppleEvent& /*outAEReply*/,
long /*inAENumber*/)
{
AEDescList docList;
OSErr err = AEGetParamDesc(&inAppleEvent, keyDirectObject,
typeWildCard, &docList);
if (err != noErr) Throw_(err);
Int32 numDocs;
err = AECountItems(&docList, &numDocs);
if (err != noErr) Throw_(err);
// Loop through all items in the list
// Extract descriptor for the document
// Coerce descriptor data into a FSSpec
// Tell Program object to open document
for (Int32 i = 1; i <= numDocs; i++) {
AEKeyword theKey;
DescType theType;
FSSpec theFileSpec;
Size theSize;
err = AEGetNthPtr(&docList, i, typeFSS, &theKey, &theType,
(Ptr) &theFileSpec, sizeof(FSSpec), &theSize);
if (err != noErr) Throw_(err);
OpenDocument(&theFileSpec);
}
AEDisposeDesc(&docList);
DoQuit();
}
void
FrDropApp::OpenDocument(
FSSpec *inMacFSSpec)
{
FSSpec saveSpec = *inMacFSSpec;
Handle curRes;
long numTypes;
long numRes;
long i, j;
short currentID;
ResType currentType;
Str255 currentName;
Str255 numString;
LHandleStream ourStream;
InsertTextIntoStream(mOutputHeaderStart, ourStream);
ourStream.WriteData(&inMacFSSpec->name[1], inMacFSSpec->name[0]);
InsertTextIntoStream(mOutputHeaderStop, ourStream);
Try_{
LFile resFile(*inMacFSSpec);
SetResLoad(false);
resFile.OpenResourceFork(fsRdPerm);
SetResLoad(true);
numTypes = Count1Types();
for(i = 1; i <= numTypes; i++)
{
Get1IndType(¤tType, i);
ThrowIfResError_();
numRes = Count1Resources(currentType);
ThrowIfResError_();
for(j = 1; j <= numRes; j++)
{
SetResLoad(false);
curRes = Get1IndResource(currentType, j);
SetResLoad(true);
ThrowIfResError_();
ThrowIfNULL_(curRes);
GetResInfo(curRes, ¤tID, NULL, currentName);
ThrowIfResError_();
// * if the resource isn't named, how does one identify it?
if(currentName[0] > 0)
{
MapToValidC(currentName); //convert name to C-language usable
// * Write a type string in the format const short kResNameType = 'type';
// InsertTextIntoStream(128, ourStream); // "const kResource"
// ourStream.WriteData(¤tName[1], currentName[0]); // "<name>"
// InsertTextIntoStream(129, ourStream); // "Type = '"
// ourStream.WriteData(¤tType, sizeof(ResType)); // "tnam"
// InsertTextIntoStream(131, ourStream); // "';\r"
// * Write an ID string in the format const short kResNameID = id#;
InsertTextIntoStream(mTextBeginLine, ourStream); // "const kResource"
ourStream.WriteData(¤tName[1], currentName[0]); // "<name>"
ourStream.WriteData(¤tType, sizeof(ResType)); //tnam
InsertTextIntoStream(mTextIDequals, ourStream); // "ID = '"
NumToString(currentID, numString);
ourStream.WriteData(&numString[1], numString[0]);
InsertTextIntoStream(mTextIDend, ourStream); // "';\r"
}
ReleaseResource(curRes);
}
}
resFile.CloseResourceFork();
// * we can now safely access our own resources
AddDotExtension(inMacFSSpec->name, kDefaultDotExtension);
StPutFile newFile("\pSave Resource Constants as:", *inMacFSSpec);
if(newFile.reply.sfGood)
{
LFile ourFile(newFile.reply.sfFile);
if(newFile.reply.sfReplacing)
ThrowIfOSErr_(FSpDelete(&newFile.reply.sfFile));
ourFile.CreateNewDataFile(kTextFileCreator, 'TEXT');
StHandleLocker stlock(ourStream.GetDataHandle());
ourFile.OpenDataFork(fsWrPerm);
ourFile.WriteDataFork(*ourStream.GetDataHandle(), ourStream.GetLength());
ourFile.CloseDataFork();
}
}
Catch_(inErr)
{
Str255 str;
NumToString(inErr,str);
ParamText(inMacFSSpec->name, str, "\p", "\p");
CautionAlert(129, NULL);
} EndCatch_
}
// * add a .dot extension to a Mac filename (yuk!)
// * this would make a good alternate constructor argument for
// * StPutFile.
void AddDotExtension(Str255 ioString, const Str255 inDot)
{
if(ioString[0] >= 32 - inDot[0]) //make space if necessary
ioString[0] -= inDot[0];
BlockMoveData(&inDot[1], &ioString[ioString[0] + 1], inDot[0]);
ioString[0] +=inDot[0];
// * yeah, I know that can be optimized
}
// * map a string to valid C chars only.
// * --not very powerful or nice, but needs at
// * least this level of translation to work properly
void MapToValidC(Str255 ioString)
{
long i;
for(i = 1; i <= ioString[0]; i++)
{
if(ioString[i] == ' ' || ioString[i] == '\t') //whitespace
{
ioString[i] = '_';
}
else if(ioString[i] > 128 || ioString[i] < 0x31)
{
ioString[i] = '_';
}
}
}
void InsertTextIntoStream(Handle inOurResource, LStream &inStream)
{
ThrowIfNULL_(inOurResource);
HLockHi(inOurResource);
inStream.WriteData(*inOurResource, GetHandleSize(inOurResource));
HUnlock(inOurResource);
}
// * insert contents of a 'TEXT' resource into an LStream
void InsertTextIntoStream(short inID, LStream &inStream)
{
Handle ourResource = Get1Resource('TEXT', inID);
InsertTextIntoStream(ourResource, inStream);
// purposely don't dispose text - res manager serves as cache mechanism
// not an efficient one, to be sure, but it works.
// * * * can't use this safely when other res forks are open unless
// * * * guarantee our home currency
}
void
FrDropApp::DoQuit()
{
mRunning = false;
}